package com.ddwl.goods.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.ddwl.common.constant.*;
import com.ddwl.common.exception.CommonException;
import com.ddwl.common.exception.ExceptionCode;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.feign.api.GateApi;
import com.ddwl.common.feign.api.OrderApi;
import com.ddwl.common.feign.api.SearchApi;
import com.ddwl.common.feign.api.ShopApi;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.MySqlUtil;
import com.ddwl.common.util.ObjectUtil;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.goods.dao.*;
import com.ddwl.goods.dao.model.*;
import com.ddwl.goods.dto.ItemStatisticsDto;
import com.ddwl.goods.mapper.CollectMapper;
import com.ddwl.goods.mapper.HistoryMapper;
import com.ddwl.goods.mapper.ItemMapper;
import com.ddwl.goods.model.*;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.distr.SetGoodsProfitBo;
import com.ddwl.schema.bo.gate.DingTalkBo;
import com.ddwl.schema.bo.goods.*;
import com.ddwl.schema.bo.order.QuerySeckillBo;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.base.RestVo;
import com.ddwl.schema.vo.dist.GoodsProfitVo;
import com.ddwl.schema.vo.goods.*;
import com.ddwl.schema.vo.order.SeckillItemVo;
import com.ddwl.schema.vo.shop.ShopVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * @author viky
 * @version 1.0.0
 * @date 2020/6/14 9:29
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ItemService {

    private final ItemMapper itemMapper;
    private final GoodsProfitDao goodsProfitDao;
    private final OrderApi orderApi;
    private final ItemDao itemDao;
    private final SkuDao skuDao;
    private final ItemMediaDao itemMediaDao;
    private final HistoryMapper historyMapper;
    private final CollectMapper collectMapper;
    private final ReserveDao reserveDao;
    private final DiscountDao discountDao;
    private final CategoryDao categoryDao;
    private final GoodsProfitService goodsProfitService;
    private final ItemTopicDao itemTopicDao;
    private final ItemTrialDao itemTrialDao;
    private final SupplierService supplierService;
    private final SearchApi searchApi;
    private final RabbitTemplate rabbitTemplate;
    private final ShopApi shopApi;
    private final ItemTagDao itemTagDao;
    private final GateApi gateApi;

    @Transactional(rollbackFor = Throwable.class)
    public String save(ItemCreateBo bo) {
        Item entity = new Item();
        BeanUtils.copyProperties(bo, entity);
        //添加供应商id
        if (StringUtils.hasText(bo.getCategoryId())) {
            Category category = categoryDao.selectByPrimaryKey(bo.getCategoryId());
            entity.setCategoryCode(category.getCategoryCode());
            entity.setSupplierId(category.getSupplierId());
        }
        if (bo.getReserveBo() != null) {
            entity.setActivitySgin(GoodsEnum.ActivityType.RESERVE.getCode().toString());
            if (Instant.now().isAfter(bo.getReserveBo().getReserveEnd())) {
                throw new CommonException(ExceptionCode.RESERVE_TIME_OUT);
            }
        }
        if (bo.getDiscountBo() != null) {
            entity.setActivitySgin(GoodsEnum.ActivityType.DISCOUNT.getCode().toString());
        }
        //获取商品列表主图
        for (ItemMediaBo itemMediaBo : bo.getMedias()) {
            if (itemMediaBo.getMediaIndex() == 1) {
                entity.setItemImage(itemMediaBo.getMediaUrl());
            }
        }
        if (!CollectionUtils.isEmpty(bo.getSkus())) {
            if (bo.getSkus().size() > 1) {
                entity.setSkuType(GoodsEnum.SkuTypeEnum.MULTIPLE.getCode());
            } else if (bo.getSkus().size() <= 1) {
                entity.setSkuType(GoodsEnum.SkuTypeEnum.SINGLE.getCode());
            }
            entity.setSkuNum(bo.getSkus().size());
            AtomicInteger stock = new AtomicInteger(0);
            bo.getSkus().forEach(skuBo -> stock.addAndGet(skuBo.getStock()));
            entity.setStock(stock.get());
        }
        //创建或更新商品
        GoodsProfit gp;
        if (StringUtils.hasText(entity.getId())) {
            if (entity.getItemStatus().equals(0)) {
                //条码判断是否重复
                barCodeUpdateUnique(bo);
                gp = calculateGoodsProfit(bo, entity);
                //设置总销量（真实+虚假；用于app小程序页面排序使用）
                entity.setSumSales(entity.getSales() + entity.getFalseSales());
                if (null == entity.getLimitFlag()) {
                    entity.setLimitFlag(BaseEnum.StatusEnum.DISABLE.getCode());
                }
                if (BaseEnum.StatusEnum.DISABLE.getCode().equals(entity.getLimitFlag())) {
                    entity.setLimitQuantity(0);
                }
                itemDao.updateByPrimaryKeySelective(entity);
            } else {
                throw new CommonException(ExceptionCode.SHELF_GOODS);
            }
            //更新审核状态为待审核
            ItemTrial itemTrial = new ItemTrial();
            itemTrial.setItemId(entity.getId());
            itemTrial.setAuditingStage(bo.getAuditingStage());
            itemTrial.setAuditingStatus(ItemTrialEnum.AuditingStatus.AUDITING_NOT.getCode());
            List<ItemTrial> itemTrials = new ArrayList<>();
            itemTrials.add(itemTrial);
            itemTrialDao.updateListByItemIdAndStage(itemTrials);
        } else {
            barCodeAddUnique(bo);
            if (bo.getSales() == null) {
                entity.setSales(0);
            }
            if (bo.getFalseSales() == null) {
                entity.setFalseSales(0);
            }
            entity.setId(UUIDGenerator.getShortUUID());
            entity.setItemStatus(BaseEnum.StatusEnum.DISABLE.getCode());
            if (bo.getItemSort() == null) {
                entity.setItemSort(0);
            }
            //获取佣金 商品佣金没有则取类目佣金 都有则取商品佣金
            gp = calculateGoodsProfit(bo, entity);
            entity.setSumSales(entity.getSales() + entity.getFalseSales());
            entity.setItemType(GoodsEnum.CategoryTypeEnum.PLATFORM.getCode());
            ShopVo shopVo = shopApi.getDefaultShopForApi().getResult();
            if (null != shopVo) {
                entity.setShopId(shopVo.getId());
                entity.setShopName(shopVo.getName());
            }
            entity.setAgencyFlag(BaseEnum.StatusEnum.DISABLE.getCode());
            entity.setDiscountFlag(BaseEnum.StatusEnum.DISABLE.getCode());
            entity.setLimitTimeFlag(BaseEnum.StatusEnum.DISABLE.getCode());
            entity.setWxaCode(getWxaCodeOSSUrl(entity.getId()));
            itemDao.insert(entity);
            //创建商品审核信息录入
            ItemTrial itemTrial = new ItemTrial();
            itemTrial.setItemId(entity.getId());
            itemTrial.setAuditingStage(ItemTrialEnum.AuditingStage.CREATE.getCode());
            itemTrial.setAuditingStatus(ItemTrialEnum.AuditingStatus.AUDITING_NOT.getCode());
            itemTrialDao.insert(itemTrial);
        }
        // 创建或更新活动
        createAndUpdateActivity(bo, entity.getId());
        //创建或更新媒体
        if (!CollectionUtils.isEmpty(bo.getMedias())) {
            createAndUpdateMedias(bo.getMedias(), entity.getId());
        }
        //创建或更新子商品
        if (!CollectionUtils.isEmpty(bo.getSkus())) {
            createAndUpdateSku(bo.getSkus(), entity.getId(), entity.getItemImage(), gp);
        }
        updateItemTag(entity.getId(), entity.getLimitFlag(), GoodsEnum.ItemTagEnum.LIMITED_BUY.getCode(), GoodsEnum.ItemTagEnum.LIMITED_BUY.getName());
        updateItemSgin(entity.getId());
        goodsProfitService.setItemProfit(bo.getGoodsProfitBo(), entity.getId());
        return entity.getId();
    }

    public String getWxaCodeOSSUrl(String itemId) {
        RestVo<String> stringRestVo = gateApi.wxaCodeUnlimit(itemId, BaseEnum.WxAppId.WBM.getCode(), String.format(GateEnum.WxaPath.ITEM_WXA_CODE.getPath(), itemId), GateEnum.WbmMinAppPage.ITEM_INDEX.getPath());
        if (StrUtil.isEmpty(stringRestVo.getResult())) {
            return null;
        }
        return stringRestVo.getResult();
    }

    private void updateItemTag(String itemId, Integer tagFlag, String tagCode, String tagName) {
        ItemTag itemTag = itemTagDao.getByItemIdAndCode(itemId, tagCode);
        if (null == itemTag && BaseEnum.StatusEnum.ENABLE.getCode().equals(tagFlag)) {
            saveItemTag(itemId, tagCode, tagName);
        }
        if (null != itemTag && BaseEnum.StatusEnum.DISABLE.getCode().equals(tagFlag)) {
            itemTagDao.deleteByItemIdAndCode(itemId, tagCode);
        }
    }

    private void updateItemSgin(String itemId) {
        String itemTagString = getItemTagString(itemId);
        if (StringUtils.hasText(itemTagString)) {
            Item entity = new Item();
            entity.setId(itemId);
            entity.setItemSgin(itemTagString);
            itemDao.updateByPrimaryKeySelective(entity);
        }
    }

    private String getItemTagString(String itemId) {
        List<ItemTag> list = itemTagDao.getByItemId(itemId);
        StringJoiner sj = new StringJoiner(",");
        list.forEach(itemTag -> {
            sj.add(itemTag.getName());
        });
        return sj.toString();
    }

    private void saveItemTag(String itemId, String tagCode, String tagName) {
        ItemTag it = new ItemTag();
        it.setItemId(itemId);
        it.setCode(tagCode);
        it.setName(tagName);
        itemTagDao.insert(it);
    }

    private GoodsProfit calculateGoodsProfit(ItemCreateBo bo, Item entity) {
        GoodsProfit gp = new GoodsProfit();
        if (bo.getGoodsProfitBo() == null) {
//            GoodsProfit goodsProfit = new GoodsProfit();
//            goodsProfit.setTargetId(bo.getCategoryId());
//            goodsProfit.setStatus(BaseEnum.StatusEnum.ENABLE.getCode());
//            gp = goodsProfitDao.selectOne(goodsProfit);
//            if (gp != null) {
//                //0是百分比 1是固定金额
//                if (gp.getProfitType().equals(Constant.PROFIT_BF)) {
//                    if (null != entity.getOriginPrice() && entity.getOriginPrice().compareTo(BigDecimal.ZERO) > 0) {
//                        entity.setItemCommission(entity.getOriginPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
//                    } else {
//                        entity.setItemCommission(entity.getRetailPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
//                    }
//                }
//                if (gp.getProfitType().equals(Constant.PROFIT_GD)) {
//                    entity.setItemCommission(gp.getRatio());
//                }
//            }
            entity.setItemCommission(BigDecimal.ZERO);
        } else {
            gp = BeanConverUtils.convertBean(bo.getGoodsProfitBo(), GoodsProfit.class);
            BigDecimal itemCommission;
            if (BaseEnum.StatusEnum.ENABLE.getCode().equals(gp.getStatus())) {
                if (null != entity.getOriginPrice() && entity.getOriginPrice().compareTo(BigDecimal.ZERO) > 0) {
                    itemCommission = getCommission(entity.getOriginPrice(), bo.getGoodsProfitBo());
                } else {
                    itemCommission = getCommission(entity.getRetailPrice(), bo.getGoodsProfitBo());
                }
            } else {
                itemCommission = BigDecimal.ZERO;
            }
            entity.setItemCommission(itemCommission);
        }
        return gp;
    }

    /**
     * 更新津贴价
     */
    @Transactional(rollbackFor = Throwable.class)
    public void updateOriginPrice() {
        List<Item> items = itemDao.selectAll();
        for (Item item : items) {
            List<Sku> byItemId = skuDao.findByItemId(item.getId(), 1);
            if (!CollectionUtils.isEmpty(byItemId)) {
                item.setOriginPrice(byItemId.get(0).getFactoryPrice());
                itemDao.updateByPrimaryKeySelective(item);
            }
        }
    }


    /**
     * 新增判断商品条码和sku编码不能重复
     *
     * @param bo
     */
    void barCodeAddUnique(ItemCreateBo bo) {
        if (StrUtil.isNotEmpty(bo.getBarcode())) {
            Item item = new Item();
            item.setBarcode(bo.getBarcode());
            //商品条码不可重复录入
            if (!itemDao.select(item).isEmpty()) {
                throw new CommonException(ExceptionCode.ITEM_BARCODE_EXISTS);
            }
        }
        //sku编码不可重复录入
        for (SkuBo skuBo : bo.getSkus()) {
            if (StringUtils.hasText(skuBo.getBarcode())) {
                Sku sku = new Sku();
                sku.setBarcode(skuBo.getBarcode());
                if (!skuDao.select(sku).isEmpty()) {
                    throw new CommonException(ExceptionCode.SKU_BARCODE_EXISTS);
                }
            }
        }
    }


    /**
     * 修改判断商品条码和sku编码不能重复
     *
     * @param bo
     */
    void barCodeUpdateUnique(ItemCreateBo bo) {
        //sku编码不可重复录入
        skuDao.deleteByItemId(bo.getId());
        for (SkuBo skuBo : bo.getSkus()) {
            if (StringUtils.hasText(skuBo.getBarcode())) {
                Sku sku = new Sku();
                sku.setBarcode(skuBo.getBarcode());
                if (!skuDao.select(sku).isEmpty()) {
                    throw new CommonException(ExceptionCode.SKU_BARCODE_EXISTS);
                }
            }
        }
    }

    /**
     * 创建更新活动
     *
     * @param bo
     */
    void createAndUpdateActivity(ItemCreateBo bo, String itemId) {
        reserveDao.deleteByItemId(itemId);
        discountDao.deleteByItemId(itemId);
        if (bo.getReserveBo() != null) {
            ReserveBo reserveBo = bo.getReserveBo();
            reserveBo.setId(UUIDGenerator.getShortUUID());
            reserveBo.setItemId(itemId);
            Reserve reserve = new Reserve();
            BeanUtils.copyProperties(reserveBo, reserve);
            reserveDao.insert(reserve);
        }
        if (bo.getDiscountBo() != null) {
            DiscountBo discountBo = bo.getDiscountBo();
            for (Map.Entry<String, String> entry : discountBo.getDiscountMap().entrySet()) {
                Discount discount = new Discount();
                discount.setItemId(itemId);
                discount.setId(UUIDGenerator.getShortUUID());
                discount.setDiscountNum(entry.getKey());
                discount.setDiscountValue(entry.getValue());
                discountDao.insert(discount);
            }
        }
    }

    /**
     * 创建更新媒体
     *
     * @param
     */
    void createAndUpdateMedias(List<ItemMediaBo> mediaList, String itemId) {
        itemMediaDao.deleteByItem(itemId);
        for (ItemMediaBo itemMediaBo : mediaList) {
            ItemMedia media = new ItemMedia();
            BeanUtils.copyProperties(itemMediaBo, media);
            media.setItemId(itemId);
            media.setId(UUIDGenerator.getShortUUID());
            itemMediaDao.insert(media);
        }
    }

    /**
     * 创建更新子商品
     *
     * @param skuBoList
     * @param itemId
     */

    public void createAndUpdateSku(List<SkuBo> skuBoList, String itemId, String imageUrl, GoodsProfit gp) {
        int index = 0;
        for (SkuBo skuBo : skuBoList) {
            Sku sku = new Sku();
            BeanUtils.copyProperties(skuBo, sku);
            if (gp != null && BaseEnum.StatusEnum.ENABLE.getCode().equals(gp.getStatus())) {
                //0是百分比 1是固定金额
                if (gp.getProfitType().equals(Constant.PROFIT_BF)) {
                    if (null != sku.getFactoryPrice() && sku.getFactoryPrice().compareTo(BigDecimal.ZERO) > 0) {
                        sku.setItemCommission(sku.getFactoryPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
                    } else {
                        sku.setItemCommission(sku.getRetailPrice().multiply(gp.getRatio()).divide(new BigDecimal(100)));
                    }
                }
                if (gp.getProfitType().equals(Constant.PROFIT_GD)) {
                    sku.setItemCommission(gp.getRatio());
                }
            } else {
                sku.setItemCommission(BigDecimal.ZERO);
            }
            if (!StringUtils.hasText(sku.getBarcode())) {
                sku.setBarcode(UUIDGenerator.getUUID());
            }
            if (!StringUtils.hasText(sku.getImageUrl())) {
                sku.setImageUrl(imageUrl);
            }
            sku.setId(UUIDGenerator.getShortUUID());
            sku.setItemId(itemId);
            sku.setDflag(0);
            sku.setSkuStatus(1);
            sku.setLockStock(0);
            sku.setIndexNum(index++);
            skuDao.insert(sku);
        }
    }


    @Transactional(rollbackFor = Throwable.class)
    public void update(ItemBo bo) {
        if (!StringUtils.hasText(bo.getId())) {
            throw new CommonException(ExceptionCode.PARAM_NULL);
        }
        Item entity = itemDao.selectByPrimaryKey(bo.getId());
        if (entity == null) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        BeanUtils.copyProperties(bo, entity, ObjectUtil.getNullFields(bo));
        //更新主表
        itemDao.updateByPrimaryKeySelective(entity);
        //更新媒体
        List<ItemMediaBo> itemMediaBos = bo.getMedias();
        if (!CollectionUtils.isEmpty(itemMediaBos)) {
            updateMedia(bo.getId(), itemMediaBos);
        }
    }

    /**
     * 更新媒体
     *
     * @param itemId
     * @param mediaBos
     */
    public void updateMedia(String itemId, List<ItemMediaBo> mediaBos) {
        for (ItemMediaBo itemMediaBo : mediaBos) {
            ItemMedia media = new ItemMedia();
            BeanUtils.copyProperties(itemMediaBo, media);
            ItemMedia itemMedia = itemMediaDao.findByItemIdAndIndex(itemId, itemMediaBo.getMediaIndex());
            if (itemMedia != null) {
                media.setGmtModified(Instant.now());
                itemMediaDao.updateByItemIdAndIndex(itemId, itemMediaBo.getMediaIndex(), media);
            } else {
                media.setItemId(itemId);
                media.setId(UUIDGenerator.getShortUUID());
                itemMediaDao.insert(media);
            }
        }
    }

    /**
     * 获取商品下的专题
     *
     * @param itemId
     * @return
     */
    public List<String> getTopic(String itemId) {
        ItemTopic itemTopic = new ItemTopic();
        itemTopic.setItemId(itemId);
        List<String> idList = itemTopicDao.select(itemTopic).stream().map(ItemTopic::getTopicId).collect(Collectors.toList());
        return idList;
    }

    /**
     * 商品标签操作
     */
    public void itemSginOperate(ItemSginBo itemSginBo) {
        if (itemSginBo.getItemSgins() != null) {
            List<String> itemSgins = itemSginBo.getItemSgins();
            StringBuilder sgins = new StringBuilder();
            for (String itemSgin : itemSgins) {
                sgins.append(itemSgin + ",");
            }
            ItemSgin itemSgin = new ItemSgin();
            itemSgin.setItemIds(itemSginBo.getItemIds());
            itemSgin.setItemSgin(sgins.toString());
            itemDao.updateItemSgins(itemSgin);
        } else {
            ItemSgin itemSgin = new ItemSgin();
            itemSgin.setItemIds(itemSginBo.getItemIds());
            itemDao.updateItemSginNull(itemSgin);
        }
    }

    /**
     * 绑定专题
     *
     * @param itemId
     * @param topicList
     */
    public int addTopic(String itemId, List<String> topicList) {
        itemTopicDao.deleteByItemId(itemId);
        if (CollectionUtils.isEmpty(topicList)) {
            return 0;
        }
        List<ItemTopic> itemTopics = new ArrayList<>();
        for (String topicId : topicList) {
            ItemTopic itemTopic = new ItemTopic();
            itemTopic.setItemId(itemId);
            itemTopic.setId(UUIDGenerator.getShortUUID());
            itemTopic.setTopicId(topicId);
            itemTopic.setItemSort(99999);
            itemTopic.setDflag(BaseEnum.DflagEnum.NOT_DELETE.getCode());
            itemTopic.setGmtModified(Instant.now());
            itemTopic.setGmtCreated(Instant.now());
            itemTopics.add(itemTopic);
        }
        return itemTopicDao.insertByList(itemTopics);
    }

    /**
     * 商品专题解绑
     *
     * @param itemId
     * @param topicId
     * @return
     */
    public int delTopic(String itemId, String topicId) {
        return itemTopicDao.deleteByItemTopicId(itemId, topicId);
    }

    /**
     * App查询商品列表附带分销配置
     *
     * @param pageBo
     * @return
     */
    public PageVo<ItemVo> distrList(PageBo<ItemSearchBo> pageBo) {
        PageVo<ItemVo> pageVo = list(pageBo);
        List<GoodsProfitVo> profitVos = goodsProfitService.queryGoodsProfitVoByItemIds(pageVo.getData().stream().map(ItemVo::getId).collect(Collectors.toList()));
        for (GoodsProfitVo profitVo : profitVos) {
            pageVo.getData().forEach(itemVo -> {
                if (itemVo.getId().equals(profitVo.getTargetId())) {
                    itemVo.setGoodsProfitVo(profitVo);
                }
            });
        }
        return pageVo;
    }

    public void itemSort(String itemId, Integer itemSort) {
        itemDao.itemSort(itemId, itemSort);
    }

    /**
     * 查询商品列表
     *
     * @param pageBo
     * @return
     */
    public PageVo<ItemVo> list(PageBo<ItemSearchBo> pageBo) {
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize(), MySqlUtil.orderBy(pageBo.getSort(), pageBo.isAsc()));
        ItemSearchBo itemSearchBo = pageBo.getParam();
        List<Item> entities = itemMapper.findAll(itemSearchBo);
        PageInfo<Item> info = new PageInfo(entities);
        /*if (itemSearchBo.getOrderType() != null && itemSearchBo.getOrderType().equalsIgnoreCase("sales") && itemSearchBo.getOrderDirection() == null) {
            Collections.reverse(entities);
        }*/
        //获取分类名称
        List<Category> categoryList = getCategories();
        Map<String, String> map = new HashMap<>();
        for (Category category : categoryList) {
            map.put(category.getId(), category.getName());
        }
        List<ItemVo> itemVos = info.getList().stream().map(item -> {
            ItemVo itemVo = new ItemVo();
            BeanUtils.copyProperties(item, itemVo);
            for (Map.Entry<String, String> entry : map.entrySet()) {
                if (itemVo.getCategoryId().equals(entry.getKey())) {
                    itemVo.setCategoryName(entry.getValue());
                }
            }
            if (StrUtil.isNotEmpty(item.getItemSgin())) {
                String[] signs = item.getItemSgin().split(",");
                itemVo.setItemSgins(Arrays.asList(signs));
            }
            return itemVo;
        }).collect(Collectors.toList());
        return new PageVo<>(info.getTotal(), pageBo.getPage(), pageBo.getPageSize(), itemVos);
    }


    /**
     * 查询主商品列表
     *
     * @param boPageBo
     * @return
     */
    public PageVo<ItemApiVo> mainItemApilist(PageBo<ItemListApiBo> boPageBo) {
        ItemListApiBo bo = boPageBo.getParam();
        ParamException.isTrue(bo.getAppId() == null, "appID为空");
        ParamException.isTrue(bo.getTimestamp() == null, "请求时间为空");
        SupplierBo supplierBo = new SupplierBo();
        supplierBo.setAppId(boPageBo.getParam().getAppId());
        PageBo pageBo = new PageBo();
        pageBo.setParam(supplierBo);
        List<SupplierVo> data = supplierService.getList(supplierBo);
        ParamException.isTrue(data == null || data.size() == 0, "appID不存在");
        List<String> supplierList = data.stream().map(SupplierVo::getId).collect(Collectors.toList());
        bo.setSupplierList(supplierList);
        PageHelper.startPage(boPageBo.getPage(), boPageBo.getPageSize(), MySqlUtil.orderBy(boPageBo.getSort(), boPageBo.isAsc()));
        List<Item> entities = itemMapper.findApiAll(bo);
        PageInfo<Item> info = new PageInfo(entities);
        List<ItemApiVo> list = BeanConverUtils.convertBeanList(info.getList(), ItemApiVo.class);
        return new PageVo<>(info.getTotal(), boPageBo.getPage(), boPageBo.getPageSize(), list);
    }

    /**
     * 管理后台查询商品列表
     *
     * @param pageBo
     * @return
     */
    public PageVo<ItemVo> conList(PageBo<ItemSearchBo> pageBo) {
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize(), MySqlUtil.orderBy(pageBo.getSort(), pageBo.isAsc()));
        ItemSearchBo itemSearchBo = pageBo.getParam();
        List<Item> entities = itemMapper.findConAll(itemSearchBo);
        PageInfo<Item> info = new PageInfo(entities);
        if (itemSearchBo.getOrderType() != null && itemSearchBo.getOrderType().equalsIgnoreCase("sales") && itemSearchBo.getOrderDirection() == null) {
            Collections.reverse(entities);
        }
        //获取分类名称
        List<Category> categoryList = getCategories();
        Map<String, String> map = new HashMap<>();
        for (Category category : categoryList) {
            map.put(category.getId(), category.getName());
        }
        List<ItemVo> itemVos = info.getList().stream().map(item -> {
            ItemVo itemVo = new ItemVo();
            BeanUtils.copyProperties(item, itemVo);
            for (Map.Entry<String, String> entry : map.entrySet()) {
                if (itemVo.getCategoryId().equals(entry.getKey())) {
                    itemVo.setCategoryName(entry.getValue());
                }
            }
            return itemVo;
        }).collect(Collectors.toList());
        return new PageVo<>(info.getTotal(), pageBo.getPage(), pageBo.getPageSize(), itemVos);
    }


    public PageVo<ItemConListVo> conListNew(PageBo<ItemSearchBo> pageBo) {
        ItemSearchBo itemSearchBo = pageBo.getParam();
        Map<String, Integer> statistics = new HashMap<>();
        List<ItemStatisticsDto> trialMapList = itemMapper.statisticsAuditing(itemSearchBo);
        List<ItemStatisticsDto> shelfMapList = itemMapper.statisticsShelf(itemSearchBo);
        Map<Integer, Integer> trialMap = new HashMap<>();
        Map<Integer, Integer> shelfMap = new HashMap<>();
        //增加审核状态统计到map
        for (ItemStatisticsDto dto : trialMapList) {
            trialMap.put(dto.getItemStatus(), dto.getCount());
        }
        for (Map.Entry<Integer, Integer> entry : trialMap.entrySet()) {
            statistics.put(ItemTrialEnum.AuditingStatus.getValueByCode(entry.getKey()), entry.getValue());
        }
        //增加上架统计到map
        for (ItemStatisticsDto dto : shelfMapList) {
            shelfMap.put(dto.getItemStatus(), dto.getCount());
        }
        for (Map.Entry<Integer, Integer> entry : shelfMap.entrySet()) {
            String name = ItemTrialEnum.IsStacking.getValueByCode(entry.getKey());
            statistics.put(name, entry.getValue());
        }
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize(), MySqlUtil.orderBy(pageBo.getSort(), pageBo.isAsc()));
        Page<Item> pageable = (Page<Item>) itemMapper.findConAllNew(itemSearchBo);
        List<Item> entities = pageable.getResult();
        if (entities.isEmpty()) {
            return new PageVo<>(pageable.getTotal(), pageBo.getPage(), pageBo.getPageSize(), new ArrayList<>(), statistics);
        }
        List<ItemTrial> itemTrials = itemTrialDao.selectByItemIds(entities.stream().map(Item::getId).collect(Collectors.toList()));
        Map<String, ItemTrial> itemTrialMap = itemTrials.stream().collect(Collectors.toMap(ItemTrial::getItemId, Function.identity(), (k1, k2) -> k1));
        //获取分类名称
        List<Category> categories = getCategories();
        Map<String, String> categoryMap = categories.stream().collect(Collectors.toMap(Category::getId, Category::getName));
        List<ItemConListVo> itemVos = entities.stream().map(item -> {
            ItemConListVo vo = BeanConverUtils.convertBean(item, ItemConListVo.class);
            if (item.getItemSgin() != null) {
                String[] sgins = item.getItemSgin().split(",");
                List<String> sginList = new ArrayList<>();
                for (String sgin : sgins) {
                    if (!sgin.equals("")) {
                        sginList.add(sgin);
                    }
                }
                vo.setItemSgins(sginList);
            }
            vo.setCategoryName(categoryMap.get(item.getCategoryId()));
            ItemTrial itemTrial = itemTrialMap.getOrDefault(item.getId(), new ItemTrial());
            vo.setAuditingStatus(itemTrial.getAuditingStatus());
            vo.setRefuseReason(itemTrial.getRefuseReason());
            vo.setIsAuditingPass(itemTrial.getIsAuditingPass());
            vo.setUndercarriageReason(itemTrial.getUndercarriageReason());
            vo.setUndercarriageRefuseReason(itemTrial.getUndercarriageRefuseReason());
            vo.setIsStacking(itemTrial.getIsStacking());
            return vo;
        }).collect(Collectors.toList());
        if (itemSearchBo.getOrderType() != null && itemSearchBo.getOrderType().equalsIgnoreCase("sales") && itemSearchBo.getOrderDirection() == null) {
            Collections.reverse(entities);
        }
        return new PageVo<>(pageable.getTotal(), pageBo.getPage(), pageBo.getPageSize(), itemVos, statistics);
    }

    private List<Category> getCategories() {
        Category entity = new Category();
        entity.setCategoryType(GoodsEnum.CategoryTypeEnum.PLATFORM.getCode());
        return categoryDao.select(entity);
    }

    /**
     * 批量设置佣金
     *
     * @param itemCommissionBo
     */
    public void itemCommissions(ItemCommissionBo itemCommissionBo) {
        SetGoodsProfitBo goodsProfitBo = itemCommissionBo.getSetGoodsProfitBo();
        Sku sku = new Sku();
        Item entity = new Item();
        for (String id : itemCommissionBo.getIds()) {
            Item item = itemDao.selectByPrimaryKey(id);
            entity.setId(item.getId());
            entity.setItemCommission(getCommission(item.getRetailPrice(), goodsProfitBo));
            itemDao.updateByPrimaryKeySelective(entity);
            sku.setItemId(id);
            List<SkuBo> skuList = skuDao.select(sku).stream().map(sk -> {
                sk.setItemCommission(getCommission(sk.getRetailPrice(), goodsProfitBo));
                SkuBo skuBo = BeanConverUtils.convertBean(sk, SkuBo.class);
                return skuBo;
            }).collect(Collectors.toList());
            skuDao.updateCommission(skuList);
            goodsProfitService.setItemProfit(goodsProfitBo, id);
        }
    }

    /**
     * 获取当前佣金
     *
     * @param price
     * @param gp
     * @return
     */
    public BigDecimal getCommission(BigDecimal price, SetGoodsProfitBo gp) {
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(gp.getStatus())) {
            if (gp.getProfitType().equals(Constant.PROFIT_BF)) {
                return price.multiply(gp.getRatio()).divide(new BigDecimal(100));
            }
            if (gp.getProfitType().equals(Constant.PROFIT_GD)) {
                return gp.getRatio();
            }
        }
        return BigDecimal.ZERO;
    }

    @Transactional(rollbackFor = Throwable.class)
    public void shelf(ItemShelfBo bo) {
        Item item = itemDao.selectByPrimaryKey(bo.getId());
        if (bo.getItemStatus().equals(BaseEnum.StatusEnum.ENABLE.getCode())) {
            if (item.getActivitySgin() != null) {
                if (item.getActivitySgin().equals(GoodsEnum.ActivityType.RESERVE.getCode().toString())) {
                    Reserve reserve = new Reserve();
                    reserve.setItemId(item.getId());
                    Reserve rs = reserveDao.selectOne(reserve);
                    if (rs != null) {
                        if (Instant.now().isAfter(rs.getReserveEnd())) {
                            throw new CommonException(ExceptionCode.RESERVE_TIEM_OUT2);
                        }
                    }
                }
            }
        }
        Item status = BeanConverUtils.convertBean(bo, Item.class);
        itemDao.updateByPrimaryKeySelective(status);
        //更新商品审核信息
        List<ItemTrial> itemTrials = new ArrayList<>();
        List<String> itemIds = new ArrayList<>();
        itemIds.add(bo.getId());
        itemTrialDao.updateStackingStatus(itemIds, bo.getItemStatus());
        //如果是下架，需要删除初审和复审阶段的审核信息，并将创建阶段的审核状态改为待审核状态
        if (bo.getItemStatus().equals(BaseEnum.StatusEnum.DISABLE.getCode())) {
            itemTrialDao.deleteAuditing(itemIds, ItemTrialEnum.AuditingStage.FIRST_TRIAL.getCode());
            itemTrialDao.deleteAuditing(itemIds, ItemTrialEnum.AuditingStage.RECHECK.getCode());
            ItemTrial itemTrialI = new ItemTrial();
            itemTrialI.setItemId(bo.getId());
            itemTrialI.setAuditingStage(ItemTrialEnum.AuditingStage.CREATE.getCode());
            itemTrialI.setAuditingStatus(ItemTrialEnum.AuditingStatus.AUDITING_NOT.getCode());
            itemTrials.add(itemTrialI);
            itemTrialDao.updateListByItemIdAndStage(itemTrials);
            itemTrialDao.updateUndercarriageReason(bo.getId(), ItemTrialEnum.AuditingStage.RECHECK.getCode());
            itemTrialDao.updateUndercarriageReason(bo.getId(), ItemTrialEnum.AuditingStage.CREATE.getCode());
        }
        searchApi.create(BeanConverUtils.convertBean(itemDao.selectByPrimaryKey(bo.getId()), ItemVo.class));
    }

    @Transactional(rollbackFor = Throwable.class)
    public void delete(String id) {
        itemDao.deleteById(id);
        itemMediaDao.deleteByItem(id);
        skuDao.deleteByItemId(id);
        //itemCategoryMapper.deleteByItem(id);
        searchApi.delete(id);
    }

    @Transactional(rollbackFor = Exception.class)
    public void itemAuditingUpdate() {
        List<Item> items = itemDao.findItemByItemStatus(BaseEnum.StatusEnum.DISABLE.getCode());
        List<ItemTrial> itemTrials = new ArrayList<>();
        for (Item item : items) {
            ItemTrial itemTrial = new ItemTrial();
            itemTrial.setItemId(item.getId());
            itemTrial.setAuditingStage(ItemTrialEnum.AuditingStage.CREATE.getCode());
            itemTrial.setAuditingStatus(ItemTrialEnum.AuditingStatus.AUDITING_NOT.getCode());
            itemTrial.setIsStacking(ItemTrialEnum.IsStacking.UNGROUNDING.getCode());
            itemTrials.add(itemTrial);
        }
        itemTrialDao.insertList(itemTrials);
        items = itemDao.findItemByItemStatus(BaseEnum.StatusEnum.DISABLE.getCode());
        itemTrials.clear();
        List<ItemTrial> itemTrialsA = new ArrayList<>();
        List<ItemTrial> itemTrialsB = new ArrayList<>();
        List<ItemTrial> itemTrialsC = new ArrayList<>();
        for (Item item : items) {
            ItemTrial itemTrialA = new ItemTrial();
            itemTrialA.setItemId(item.getId());
            itemTrialA.setAuditingStage(ItemTrialEnum.AuditingStage.CREATE.getCode());
            itemTrialA.setAuditingStatus(ItemTrialEnum.AuditingStatus.AUDITING_PASS.getCode());
            itemTrialA.setIsStacking(ItemTrialEnum.IsStacking.GROUNDING.getCode());
            itemTrialsA.add(itemTrialA);
            ItemTrial itemTrialB = new ItemTrial();
            itemTrialB.setItemId(item.getId());
            itemTrialB.setAuditingStage(ItemTrialEnum.AuditingStage.FIRST_TRIAL.getCode());
            itemTrialB.setAuditingStatus(ItemTrialEnum.AuditingStatus.AUDITING_PASS.getCode());
            itemTrialB.setIsStacking(ItemTrialEnum.IsStacking.GROUNDING.getCode());
            itemTrialB.setIsAuditingPass(ItemTrialEnum.IsAudithingPass.PASS.getCode());
            itemTrialsB.add(itemTrialB);
            ItemTrial itemTrialC = new ItemTrial();
            itemTrialC.setItemId(item.getId());
            itemTrialC.setAuditingStage(ItemTrialEnum.AuditingStage.RECHECK.getCode());
            itemTrialC.setAuditingStatus(ItemTrialEnum.AuditingStatus.AUDITING_PASS.getCode());
            itemTrialC.setIsStacking(ItemTrialEnum.IsStacking.GROUNDING.getCode());
            itemTrialC.setIsAuditingPass(ItemTrialEnum.IsAudithingPass.PASS.getCode());
            itemTrialsC.add(itemTrialC);
        }
        itemTrialDao.insertList(itemTrialsA);
        itemTrialDao.insertList(itemTrialsB);
        itemTrialDao.insertList(itemTrialsC);

    }

    /**
     * sku-成本价Excel导入
     *
     * @param file
     * @return
     * @throws IOException
     */
    public int excelIn(MultipartFile file) throws IOException {
        //得到文件的名称
        String fileName = file.getOriginalFilename();
        //获取文件的后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        List<SkuBo> skuBoList = new ArrayList<>();
        if (suffix.equals(".xls")) {
            // 建立Excel对象
            HSSFWorkbook workbook = new HSSFWorkbook(new POIFSFileSystem(file.getInputStream()));
            // 获取Excel中的sheet数量
            int numberOfSheets = workbook.getNumberOfSheets();
            for (int i = 0; i < numberOfSheets - 1; i++) {
                // 获取excel sheet
                HSSFSheet sheet = workbook.getSheetAt(i);
                // 获取行的数量
                int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
                if (physicalNumberOfRows <= 1) {
//                    workbook.close();
                    throw new CommonException("excel表格异常");
                }
                for (int j = 0; j < physicalNumberOfRows; j++) {
                    // 如果有标题则第一列不进行加载
                    if (j == 0) {
                        continue;// 标题行
                    } else {
                        // 获取该行的数据信息
                        HSSFRow row = sheet.getRow(j);
                        // 需要对每一行的数据进行一下非空处理
                        SkuBo skuBo = new SkuBo();
                        if (row != null && row.getCell(0) != null && !row.getCell(0).getStringCellValue().trim().isEmpty()) {
                            //下标识从0开始的
                            skuBo.setBarcode(row.getCell(0).getStringCellValue());//转成字符串
                        }
                        if (row != null && row.getCell(1) != null && !row.getCell(1).getStringCellValue().trim().isEmpty()) {
                            //下标识从0开始的
                            skuBo.setFactoryPrice(new BigDecimal(row.getCell(1).getStringCellValue()));//转成字符串之后再转成BigDecimal
                        }
                        skuBoList.add(skuBo);
                    }
                }
            }
//            workbook.close();
        }
        //xlsx和xls的区别在于xlsx使用的是XSSFWorkbook
        if (suffix.equals(".xlsx")) {
            // 建立Excel对象
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
            // 获取Excel中的sheet数量
            int numberOfSheets = workbook.getNumberOfSheets();
            //最后一个sheet放枚举 不进行加载
            for (int i = 0; i < numberOfSheets - 1; i++) {
                // 获取excel sheet
                XSSFSheet sheet = workbook.getSheetAt(i);
                // 获取行的数量
                int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
                if (physicalNumberOfRows <= 1) {
//                    workbook.close();
                    throw new CommonException("excel表格异常");
                }
                for (int j = 0; j < physicalNumberOfRows; j++) {
                    // 如果有标题则第一列不进行加载
                    if (j == 0) {
                        continue;// 标题行
                    } else {
                        // 获取该行的数据信息
                        XSSFRow row = sheet.getRow(j);
                        SkuBo skuBo = new SkuBo();
                        if (row != null && row.getCell(0) != null && !row.getCell(0).getStringCellValue().trim().isEmpty()) {
                            //下标识从0开始的
                            skuBo.setBarcode(row.getCell(0).getStringCellValue());//转成字符串
                            skuBo.setFactoryPrice(new BigDecimal(row.getCell(1).getNumericCellValue()));
                        }
                        skuBoList.add(skuBo);
                    }
                }
            }
//            workbook.close();
        }
        return skuDao.updateFactoryPrice(skuBoList);
    }

    public ItemVo barcode(String barcode) {
        ItemVo entity = itemMapper.findByBarcode(barcode);
        if (entity == null) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        return convert(entity);
    }

    public ItemVo getItem(String id) {
        return BeanConverUtils.convertBean(itemDao.selectByPrimaryKey(id), ItemVo.class);
    }

    public ItemVo getItemWithShop(String id, String shopId) {
        return BeanConverUtils.convertBean(itemMapper.findItemWithShop(id, shopId), ItemVo.class);
    }

    public ItemVo getById(String id) {
        ItemVo itemVo = itemDao.getDetailsById(id);
        if (itemVo == null) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        return convert(itemVo);
    }

    private ItemVo convert(ItemVo entity) {
        ItemVo vo = new ItemVo();
        BeanUtils.copyProperties(entity, vo);
        if (entity.getItemSgin() != null) {
            String[] sgins = entity.getItemSgin().split(",");
            List<String> sginList = new ArrayList<>();
            for (String sgin : sgins) {
                if (!sgin.equals("")) {
                    sginList.add(sgin);
                }
            }
            vo.setItemSgins(sginList);
        }
        return vo;
    }

    @Transactional(rollbackFor = Throwable.class)
    public ItemDetailVo detail(String id, String userId, String seckillId) {
        ItemDetailVo vo = BeanConverUtils.convertBean(itemDao.getItemDetailById(id), ItemDetailVo.class);
        if (null == vo) {
            return null;
        }
        //  用户访问加入我的足迹中
        if (StringUtils.hasText(userId)) {
            historyMapper.insert(new History(UUIDGenerator.getShortUUID(), userId, id, null));    //没有用户产品模块时不启用
            Collect collect = collectMapper.findByUserIdAndItemId(userId, id);
            if (collect != null) {
                vo.setCollect(1);
            } else {
                vo.setCollect(0);
            }
        }
        if (vo.getActivitySgin() != null) {
            //预约购
            if (vo.getActivitySgin().equals(GoodsEnum.ActivityType.RESERVE.getCode().toString())) {
                Reserve reserve = reserveDao.queryReserveByItemId(id);
                if (null != reserve) {
                    ReserveVo reserveVo = new ReserveVo();
                    BeanUtils.copyProperties(reserve, reserveVo);
                    vo.setReserveVo(reserveVo);
                }
            }
            //满减购
            if (vo.getActivitySgin().equals(GoodsEnum.ActivityType.DISCOUNT.getCode().toString())) {
                List<Discount> discountList = discountDao.getItemDiscountByItemId(id);
                DiscountVo discountVo = new DiscountVo();
                Map<String, String> map = new HashMap<>();
                for (Discount discount : discountList) {
                    map.put(discount.getDiscountNum(), discount.getDiscountValue());
                }
                discountVo.setDiscountMap(map);
                vo.setDiscountVo(discountVo);
            }
        }
        List<SkuVo> list = vo.getSkus();
        if (!CollectionUtils.isEmpty(list)) {
            QuerySeckillBo bo = new QuerySeckillBo();
            bo.setItemId(list.get(0).getItemId());
            bo.setSeckillId(seckillId);
            List<SeckillItemVo> seckillItemVos = orderApi.querySeckillItemDetail(bo).getResult();
            vo.setSeckillItemVos(seckillItemVos);
            if (!CollectionUtils.isEmpty(seckillItemVos)) {
                vo.getSkus().stream().forEach(o -> {
                    seckillItemVos.stream().forEach(m -> {
                        if (o.getBarcode().equals(m.getBarcode())) {
                            o.setSeckillItemVo(m);
                        }
                    });
                });
            }
        }
        List<ItemTag> itemTags = itemTagDao.getByItemId(id);
        if (!CollectionUtils.isEmpty(itemTags)) {
            vo.setItemTagList(BeanConverUtils.convertBeanList(itemTags, ItemTagVo.class));
        }
        vo.setGoodsProfitVo(goodsProfitService.queryGoodsProfitVoByItemId(vo.getId()));
        return vo;
    }

    public List<ItemVo> getByIds(List<String> ids) {
        List<ItemVo> entities = itemDao.findListByIds(ids);
        if (entities.isEmpty()) {
            return new ArrayList<>(0);
        }
        return entities.stream().map(entity -> convert(entity)).collect(Collectors.toList());
    }

    public List<ItemVo> getByItemIds(List<String> ids) {
        if (CollUtil.isEmpty(ids)) {
            return null;
        }
        List<Item> entities = itemDao.selectByPrimaryKeys(ids);
        return BeanConverUtils.convertBeanList(entities, ItemVo.class);
    }


    /**
     * 更新商品佣金（数据订正使用）
     */
    public void updateCommission() {
        ItemSearchBo itemSearchBo = new ItemSearchBo();
        List<Item> items = itemDao.findConAll(itemSearchBo);
        for (Item item : items) {
            GoodsProfit goodsProfit = new GoodsProfit();
            goodsProfit.setTargetId(item.getId());
            GoodsProfit rgp = goodsProfitDao.selectOne(goodsProfit);
            SetGoodsProfitBo setGoodsProfitBo = new SetGoodsProfitBo();
            Item update = new Item();
            update.setId(item.getId());
            if (rgp == null) {
                goodsProfit.setTargetId(item.getCategoryId());
                rgp = goodsProfitDao.selectOne(goodsProfit);
            }
            BeanUtils.copyProperties(rgp, setGoodsProfitBo);
            update.setItemCommission(getCommission(item.getRetailPrice(), setGoodsProfitBo));
            itemDao.updateCommission(update);
        }

    }

    /**
     * 下架时间过期的预售商品
     */
    public void recoverReserve() {
        List<Item> items = itemDao.selectAll();
        for (Item item : items) {
            if (item.getActivitySgin() != null) {
                if (item.getActivitySgin().equals(GoodsEnum.ActivityType.RESERVE.getCode().toString())) {
                    Reserve reserve = new Reserve();
                    reserve.setItemId(item.getId());
                    Reserve rs = reserveDao.selectOne(reserve);
                    if (rs != null) {
                        if (Instant.now().isAfter(rs.getReserveEnd())) {
                            Item status = new Item();
                            status.setId(item.getId());
                            status.setItemStatus(BaseEnum.StatusEnum.DISABLE.getCode());
                            itemDao.updateByPrimaryKeySelective(status);
                        }
                    }
                }
            }

        }
    }

    /**
     * 分页查询所有商品
     *
     * @param bo
     * @return
     */
    public PageVo<ItemVo> queryAllItem(PageBo bo) {
        PageHelper.startPage(bo.getPage(), bo.getPageSize());
        Item item = new Item();
        item.setItemStatus(GoodsEnum.ItemStatus.ONLINE.getCode().intValue());
        PageInfo<Item> info = new PageInfo(itemDao.select(item));
        List<ItemVo> list = BeanConverUtils.convertBeanList(info.getList(), ItemVo.class);
        return new PageVo(info.getTotal(), bo.getPage(), bo.getPageSize(), assemblyItem(list));
    }

    /**
     * 查询商品包括sku信息
     *
     * @param bo
     * @return
     */
    public List<SkuDtoVo> querySkuWithItem(ItemListBo bo) {
        List<SkuDtoVo> skuDtoVos = BeanConverUtils.convertBeanList(itemDao.querySkuWithItem(bo), SkuDtoVo.class);
        return skuDtoVos;
    }

    /**
     * 查询商品包括sku信息
     *
     * @param bo
     * @return
     */
    public Integer querySkuWithItemCount(ItemListBo bo) {
        Integer skuWithItemCount = itemDao.querySkuWithItemCount(bo);
        return skuWithItemCount;
    }

    /**
     * 查询商品
     *
     * @param itemIds
     * @return
     */
    public List<ItemVo> queryItems(Collection<String> itemIds) {
        return BeanConverUtils.convertBeanList(itemDao.selectByPrimaryKeys(itemIds), ItemVo.class);
    }

    /**
     * 发送0库存信息
     *
     * @param bo
     * @return
     */
    public void sendZeroCountMessage(ItemListBo bo) {
        //Integer skuWithItemCount = itemDao.querySkuWithItemCount(bo);
        //发送钉钉消息
        DingTalkBo bo1 = new DingTalkBo();
        bo1.setMessage("");
        bo1.setChannel(StatisticsEnum.channel.ZERO_COUNT_ITEM.getId());
        rabbitTemplate.convertAndSend(RabbitMqConstants.DINGDING_TALK_MESSAGE, JSON.toJSONString(bo1));
    }

    private List<ItemVo> assemblyItem(List<ItemVo> list) {
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }
        List<Category> categories = getCategories();
        categories.forEach(c -> {
            list.forEach(i -> {
                if (c.getId().equals(i.getCategoryId())) {
                    i.setCategoryName(c.getName());
                }
            });
        });
        return list;
    }

    public void generateWxaCode() {
        new Thread(() -> updateWxaCode()).start();
    }

    private void updateWxaCode() {
        List<Item> items = itemDao.selectHasNoWxaCode();
        items.forEach(item -> {
            Item entity = new Item();
            entity.setId(item.getId());
            entity.setWxaCode(getWxaCodeOSSUrl(item.getId()));
            itemDao.updateByPrimaryKeySelective(entity);
        });
    }

    public void downWxaCode(HttpServletResponse response, List<String> itemIds, String shopId) {
        if (CollectionUtils.isEmpty(itemIds)) {
            return;
        }
        List<Item> items = itemDao.selectByPrimaryKeys(itemIds);
        if (CollectionUtils.isEmpty(items)) {
            return;
        }
        downForZip(response, items, shopId);
    }

    /**
     * 批量下载为zip
     */
    public void downForZip(HttpServletResponse response, List<Item> items, String shopId) {
        String fileName = "商品小程序码压缩包.zip";
        // 创建临时文件
        File zipFile = null;
        FileInputStream fis = null;
        BufferedInputStream buff = null;
        OutputStream out = null;
        try {
            //临时文件名称
            zipFile = File.createTempFile("商品小程序码压缩包", ".zip");

            FileOutputStream f = new FileOutputStream(zipFile);
            /**
             * 作用是为任何OutputStream产生校验和
             * 第一个参数是制定产生校验和的输出流，第二个参数是指定Checksum的类型 （Adler32（较快）和CRC32两种）
             */
            CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
            // 用于将数据压缩成Zip文件格式
            ZipOutputStream zos = new ZipOutputStream(csum);
            for (Item item : items) {
                try {
                    String imgName = item.getId();
                    if (StringUtils.hasText(shopId)) {
                        imgName += "_" + shopId;
                    }
                    String base64 = gateApi.getOSSBase64(String.format(GateEnum.WxaPath.ITEM_WXA_CODE.getPath(), imgName)).getResult();
                    if (!StringUtils.hasText(base64)) {
                        continue;
                    }
                    InputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(base64));
                    // 对于每一个要被存放到压缩包的文件，都必须调用ZipOutputStream对象的putNextEntry()方法，确保压缩包里面文件不同名
                    String name = item.getItemName() + item.getWxaCode().substring(item.getWxaCode().lastIndexOf("."));
                    zos.putNextEntry(new ZipEntry(name));
                    int bytesRead = 0;
                    // 向压缩文件中输出数据
                    while ((bytesRead = inputStream.read()) != -1) {
                        zos.write(bytesRead);
                    }
                    inputStream.close();
                    zos.closeEntry(); // 当前文件写完，定位为写入下一条项目
                } catch (Exception e) {
                    log.error("处理图片异常", e);
                }
            }
            zos.close();
            fileName = new String(fileName.getBytes(), "ISO8859-1");
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

            fis = new FileInputStream(zipFile);
            buff = new BufferedInputStream(fis);
            out = response.getOutputStream();
            byte[] car = new byte[1024];
            int l = 0;
            while (l < zipFile.length()) {
                int j = buff.read(car, 0, 1024);
                l += j;
                out.write(car, 0, j);
            }
            out.flush();
            out.close();
            buff.close();
            fis.close();
            zipFile.delete();
        } catch (IOException e1) {
            log.error("下载商品小程序码时出错", e1);
            throw new CommonException("下载商品小程序码时出错");
        } catch (Exception e) {
            log.error("下载商品小程序码时出错", e);
            throw new CommonException("下载商品小程序码时出错");
        }
    }


}
